#pragma once

#include <hacks/base/hacks_conf.h>
#include <hacks/base/spin_lock.h>

namespace hacks {

    typedef enum {
        mode_default = 0x00,
        mode_once,
        mode_nowait
    } run_mode;

    typedef enum {
        evl_init = 0x00,
        evl_running,
        evl_closing,
        evl_closed
    } event_loop_status;

    struct ev_loop_buffer {

        std::size_t len;

        char *data;

        explicit ev_loop_buffer(std::size_t sz)
                : len(sz),
                  data(nullptr) {
            if (len == 0) {
                return;
            }
            data = new char[len]{0};
        }

        ~ev_loop_buffer() {
            delete[] data;
        }
    };

    class ev_loop;

    //shared type
    SHARED_TYPE(ev_loop);

    typedef std::function<void()> ev_loop_functor;

#define EV_LOOP_DEFAULT_BUF_SZ (1024*6)

    class ev_loop : public std::enable_shared_from_this<ev_loop> {

    DISABLE_COPY_MOVE(ev_loop)

    public:
        /**
         * 该buf用作event loop的读写
         * 如果长度为0,则不会建立buff
         * 此时loop不能用作stream的io
         * @param bf_sz buf大小
         */
        explicit ev_loop(std::size_t bf_sz = EV_LOOP_DEFAULT_BUF_SZ);

        //if u already call run_loop, u must call stop_loop , before dealloc
        ~ev_loop();

        void run_loop(run_mode = mode_default);

        void stop_loop();

        int run_in_loop(ev_loop_functor &&action);

        bool in_event_loop() const;

        event_loop_status get_loop_status() const;

        uv_loop_t *get_raw_loop() const;

        ev_loop_buffer &get_loop_buffer();

    private:
        static void event_loop_async_callback(uv_async_t *);

        static void event_loop_handlers_close_callback(uv_handle_t *);

    private:
        std::atomic_int loop_status_;
        uv_loop_t *raw_loop_;
        uv_async_t *raw_async_;
        hacks::spin_lock lock_;
        std::list<ev_loop_functor> pendding_actions_;
        std::thread::id run_in_thread_id_;
        ev_loop_buffer rw_buffer_;

    };
}
